home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
utils
/
sharsrc.arc
/
shar.c
< prev
Wrap
C/C++ Source or Header
|
1990-03-20
|
15KB
|
630 lines
/*
* Shar puts readable text files together in a package
* from which they are easy to extract.
*
* v 860716 M. Kersenbrock (tektronix!copper!michaelk) for Z80-CPM
* - enhanced usage message
*
* v 860712 D. Wecker for ULTRIX and the AMIGA
* - stripped down.. does patterns but no directories
* - added a -u (unshar) switch
*
* v 870128 R. Royar for ST
* - removed #ifdefs that left stray }s in file
* - reformatted text for consistant style
* - modified main to abort when no files are given
* - fixed call to fputc in tell macro, which omitted the stream
* causing address errors on the ST.
* - fixed STUPID coding in getopt that tried to write to
* address 0++.
* - known bugs:
* still no directory support. Extracting
* files with directory names will get
* only the directory name on an open call.
*
* v 880713 J. Altstadt for ST
* - removed extraneous #ifdefs for all other systems
* - reformatted text for consistant style
* - changed lots of things for unsharing:
* 1. added directory handling
* 2. added code to handle weird shar sed formats better,
* will add more things when i get files that i can't unshar,
* eg. when i get one of those icky sharchives that has split files
* but won't add in the ability to handle shars that use awk to
* extract files (yes, windsrch uses awk, blech!!!)
* 3. added in file overwrite protection, i didn't need it, but it was
* easy (and i know i will need it some day when i don't have a
* backup)
* 4. skip whitespace at begining of lines intended for sh, so it will
* do stuff embedded in "if test" structures
*
* v 890124 J. Altstadt for ST
* - unshar will handle files split across two (or more) sharchives
* - fixed bug that would allow creation of directories (files) with
* the same name as an existing file (directory)
*/
#include <stdio.h>
#include <osbind.h>
#include <ctype.h>
#include <stat.h>
long _stksize = 16 * 1024; /* for 10k stack */
char *Defenv = "ENOENV"; /* if no cc.ini file */
extern char *getenv(),*malloc(),*index();
void shar();
#define BADCH ((int)'?')
#define EMSG ""
#define tell(s) {fputs(*nargv,stderr);fputs((s),stderr);fputc('\n',stderr);}
#define rescanopts() (optind = 1)
int optind = 1, /* index into parent argv vector */
optopt; /* character checked for validity */
long fsize; /* length of file */
char *optarg; /* argument associated with option */
char *sav[100]; /* saved file names */
int savind; /* save index */
/* OPTIONS */
int Verbose = 0; /* provide append/extract feedback */
int Basename = 0; /* extract into basenames */
int Count = 0; /* count characters to check transfer */
char *Delim = "SHAR_EOF"; /* put after each file */
char Filter[100] = "cat"; /* used to extract archived files */
char *Prefix = NULL; /* line prefix to avoid funny chars */
int OverWrite = 0; /* do we overwrite an output file? */
char Usage1[] =
"\nSHAR: Create/extract file archive for extraction by /bin/sh (normally).\n\
\n\
usage: shar [[-uo] archive] [[-a] [-p prefix]\
[-d delim] [-bcv] files > archive]\n\
\n\
where: -a all the options (v,c,b,-pXX)\n";
char Usage2[] =
" -b extract absolute paths into current directory\n\
-c check filesizes on extraction\n\
-d use this EOF delimiter instead of SHAR_EOF\n";
char Usage3[] =
" -o unshar <archive>, overwriting old files\n\
-p use this as prefix to each line in archived files\n\
-u unshar <archive>, not overwriting old files\n\
-v verbose on extraction, incl. echoing filesizes\n";
#define SED "sed 's/^%s//'" /* used to remove prefix from lines */
#define OPTSTRING "u:o:ap:d:bcv"
void main(argc, argv)
int argc;
char **argv;
{
char *ppchFiles[256];
register int C;
char **ppchList = ppchFiles;
register int errflg;
errflg = 0;
while(EOF != (C = getopt(argc, argv, OPTSTRING))) {
switch(C) {
case 'v':
Verbose++;
break;
case 'c':
Count++;
break;
case 'b':
Basename++;
break;
case 'd':
Delim = optarg;
break;
case 'a': /* all the options */
optarg = "X";
Verbose++;
Count++;
Basename++;
/* fall through to set prefix */
case 'p':
sprintf(Filter, SED, Prefix = optarg);
break;
case 'o':
OverWrite++;
case 'u':
dounshar(optarg);
exit(0);
break;
default:
errflg++;
}
}
C = getarg(argc, argv);
if (errflg || EOF == C) {
if (EOF == C)
fprintf(stderr, "shar: No input files\n");
fprintf(stderr, "%s%s%s", Usage1, Usage2, Usage3);
exit(1);
}
savind = 0;
do {
if (getpat(optarg)) exit(2);
} while (EOF != (C = getarg(argc, argv)));
sav[savind] = 0;
header(sav);
for (ppchList = sav; *ppchList; ++ppchList)
shar(*ppchList);
puts("#\tEnd of shell archive");
puts("exit 0");
exit(0);
}
int header(ppchFiles)
char *ppchFiles[];
{
char clock[40];
register char **ppchList;
char *pchOrg;
char *pchName;
register int problems;
problems = 0;
pchOrg = getenv("organization");
pchName = getenv("name");
puts("#\tThis is a shell archive.");
puts("#\tRemove everything above and including the cut line.");
puts("#\tThen run the rest of the file through sh.");
puts("#----cut here-----cut here-----cut here-----cut here----#");
puts("#!/bin/sh");
puts("# shar: Shell Archiver");
puts("#\tRun the following text with /bin/sh to create:");
for (ppchList = ppchFiles; *ppchList; ++ppchList)
printf("#\t%s\n", *ppchList);
stime(clock);
printf("# This archive created: %s",clock);
if (pchName)
printf("# By:\t%s (%s)\n", pchName,pchOrg);
return(0);
}
/* create an ASCII time string and copy it into timeline. Caller
* should make sure timeline has ~35 characters space.
*/
stime(timeline)
char timeline[];
{
register int mytime;
register int date;
register int hours, minutes, seconds;
int day, month, year;
static char *months[] = {"January","February","March","April",
"May","June","July","August","September",
"October","November","December"};
char *tzone;
tzone = getenv("timezone");
mytime = Tgettime();
date = Tgetdate();
seconds = (mytime&31)*2;
minutes = (mytime>>5)&63;
hours = (mytime>>11)&31;
day = (date&31);
month = ((date>>5)&15)-1;
year = ((date>>9)&31)+1980;
sprintf(timeline,"%02d-%s-%d %d:%02d:%02d %s\n",
day,months[month],year,hours,minutes,seconds,tzone);
return(1);
}
int
archive(input, output)
char *input, *output;
{
char line[BUFSIZ];
register FILE *ioptr;
if (ioptr = fopen(input, "r")) {
printf("%s << \\%s > %s\n", Filter, Delim, output);
while(fgets(line, BUFSIZ, ioptr)) {
if (Prefix)
fputs(Prefix, stdout);
fputs(line, stdout);
if (Count)
fsize += strlen(line);
}
puts(Delim);
fclose(ioptr);
return(0);
}
else {
fprintf(stderr, "shar: Can't open '%s'\n", input);
return(1);
}
}
void shar(file)
char *file;
{
register char *basefile;
basefile = file;
if (!strcmp(file, "."))
return;
fsize = 0;
if (Basename) {
while(*basefile)
basefile++; /* go to end of name */
while(basefile > file && *(basefile-1) != '/')
basefile--;
}
if (Verbose)
printf("echo shar: extracting %s\n", basefile);
if (archive(file, basefile))
exit(66);
if (Count) {
printf("if test %ld -ne \"`wc -c %s`\"\n",fsize,basefile);
printf("then\necho shar: error transmitting %s ",basefile);
printf("'(should have been %ld characters)'\nfi\n",fsize);
}
}
getpat(pattern)
char *pattern;
{
register char *ptr;
ptr = pattern;
sav[savind] = malloc(strlen(ptr)+1);
strcpy(sav[savind++],ptr);
if (access(ptr,4)) {
printf("No read access for file: %s\n",ptr);
return(-1);
}
return(0);
}
/*
* get option letter from argument vector
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char **nargv, *ostr;
{
register char *oli; /* option letter list index */
static char *place = EMSG; /* option letter processing */
if(!*place) { /* update scanning pointer */
if(optind >= nargc || *(place = nargv[optind])
!= '-' || !*++place)
return(EOF);
if (*place == '-') { /* found "--" */
++optind;
return(EOF);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':'
|| !(oli = index(ostr,optopt))) {
if(!*place)
++optind;
tell(": illegal optio